home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Libraries / SAT 2.3a1 / HeartQuest sample ƒ / gameWindow.p < prev    next >
Encoding:
Text File  |  1994-11-11  |  21.6 KB  |  719 lines  |  [TEXT/PJMM]

  1. {================================================}
  2. {=============== Game window handler ================}
  3. {================================================}
  4.  
  5. { Example file for Ingemars Sprite Animation Toolkit. }
  6. { © Ingemar Ragnemalm 1992-1994 }
  7. { See doc files for legal terms for using this code. }
  8.  
  9. { This file holds the game window and game menu handlers for HeartQuest.}
  10. { This is where most game-specific code goes, except for the code describing}
  11. { each object. }
  12.  
  13. { GameWindInit is called to initialize, which initializes the window and installs}
  14. {handler procedures (note that menus are installed in main.p). It calls the routines}
  15. {to initialize offscreen GrafPorts and all the animated objects. }
  16.  
  17. { When the user selects New Game, StartGame is called to set up a new}
  18. { game, and then MoveIt, the game driver routine is called. }
  19.  
  20. unit GameWindow;
  21.  
  22. interface
  23.  
  24.     uses
  25. {$IFC UNDEFINED THINK_PASCAL}
  26.         Types, Quickdraw, 
  27. {$ENDC}
  28.         TransSkel, SAT, {}
  29.         GameGlobals, sPlayer, sFlypaper, sHeart, sBonus, sPoints, scores, SoundConst, Sound;
  30.  
  31.     procedure DoGameMenu (item: integer);
  32.     procedure GameWindInit;
  33.     procedure DoGameOver;
  34.  
  35.  
  36. implementation
  37.  
  38. {var}
  39. {mp: MonsterPtr; { Bra att ha en global tillgänglig. Dvs praktiskt... }
  40. {    SlemtorksHandlerPtr: ProcPtr;}
  41.  
  42.     procedure InitSprites;
  43.     begin
  44. { Call the init routines for each the sprite unit! Don't forget this! }
  45.         InitFlypaper;
  46.         InitHeart;
  47.         InitPlayer;
  48.         InitBonus;
  49.         InitPoints;
  50.     end;
  51.  
  52.     procedure DrawBackground;
  53.     forward;
  54.  
  55.  
  56. { Setup a bonus level. This is called when a level finishes and all bonus objects were collected.}
  57.     procedure SetupBonusLevel (level: integer);
  58.         var
  59.             p: point;
  60.             i: integer;
  61.             mp: SpritePtr;
  62.             r: rect;
  63.             s: Str255;
  64.             er: EventRecord; {For EventAvail}
  65.             strwidth: integer;
  66.  
  67.     begin { SetupBonusLevel }
  68.  
  69.         SATSoundPlay(drringH, 10, false);
  70. {SATSoundEvents; Not needed since we call SATRun soon.}
  71.  
  72. { Clear the sprite list }
  73.         while gSAT.sRoot <> nil do
  74.             SATKillSprite(gSAT.sRoot);
  75.  
  76.         bonusLevelRunning := true;
  77.  
  78. { Create all the sprites for the level, depending on the level number. }
  79.  
  80. {batchCount := level * 2 + 10;}
  81.         for i := 1 to level * 2 + 10 do
  82.             mp := SATNewSprite(-2, Rand(gSAT.offSizeH - 112) + 17, -Rand(400 + 25 * level), @SetupBonusHeart);
  83.  
  84. { Reposition mouse to the center of the game area. }
  85.         p.h := 256;
  86.         p.v := 171;
  87.         SetMouse(p);
  88. { Make the player sprite. }
  89.         mp := SATNewSprite(2, (gSAT.offSizeH - xsize) div 2, gSAT.offSizeV div 2, @SetupPlayer);
  90. { Copy gSAT.backScreen to gSAT.offScreen to erase old sprites. }
  91.         CopyBits(gSAT.backScreen^.portBits, gSAT.offScreen^.portBits, gSAT.offScreen^.portRect, gSAT.offScreen^.portRect, srcCopy, nil);
  92.         SATRedraw; {replaces the following out-commented lines:}
  93.  
  94.         AddScore(0);
  95. { Do one frame of animation just to draw all the objects. }
  96.         SATRun(false); {false or features^^.PlotFast; slow is ok - no hurry!}
  97.  
  98.         strwidth := StringWidth(MyGetIndString(startbonusStrID));
  99.  
  100. { Draw a message and wait for click- this is a bit ugly. Consider other ways. }
  101.         SetPort(gSAT.wind);
  102.         SetRect(r, gSAT.offSizeH div 2 - strwidth div 2 - 5 + 2, gSAT.offSizeV div 2 + 35 + 2, gSAT.offSizeH div 2 + strwidth div 2 + 5 + 2, gSAT.offSizeV div 2 + 60 + 2); {offset by 2 pixels}
  103.         PaintRect(r);
  104.         SetRect(r, gSAT.offSizeH div 2 - strwidth div 2 - 5, gSAT.offSizeV div 2 + 35, gSAT.offSizeH div 2 + strwidth div 2 + 5, gSAT.offSizeV div 2 + 60);
  105.         EraseRect(r);
  106.  
  107.         MoveTo(gSAT.offSizeH div 2 - strwidth div 2, gSAT.offSizeV div 2 + 50);
  108.         DrawString(MyGetIndString(startbonusStrID)); {str 16: Click mouse for bonus level!}
  109.  
  110. {Wait until something happens}
  111.         FlushEvents(everyEvent, 0); { To forget events, like mouse clicks etc. }
  112.         repeat
  113.         until EventAvail(mDownMask + keyDownMask, er);
  114.  
  115. { Redraw to get rid of the message we just made. }
  116.         SATRedraw;
  117.     end; { SetupBonusLevel }
  118.  
  119. { Setup a new level. This is called when the game starts ans at each new level.}
  120.     procedure SetupLevel (level: integer);
  121.         var
  122.             p: point;
  123.             i: integer;
  124.             mp, oldmp: SpritePtr;
  125.             r: rect;
  126.             s: Str255;
  127.             er: EventRecord; {For EventAvail}
  128.             strwidth: integer;
  129.  
  130. { A routine to create a bunch of hearts }
  131.         procedure MakeHearts (howmany: integer);
  132.             var
  133.                 i: integer;
  134.                 mp: SpritePtr;
  135.         begin
  136.             for i := 1 to howmany do
  137.                 case rand(4) of
  138.                     0: 
  139.                         mp := SATNewSprite(-2, Rand(gSAT.offSizeH - 112) + 17, 0, @SetupHeart);
  140.                     1: 
  141.                         mp := SATNewSprite(-2, Rand(gSAT.offSizeH - 112) + 17, gSAT.offSizeV - 32, @SetupHeart);
  142.                     2: 
  143.                         mp := SATNewSprite(-2, 0, Rand(gSAT.offSizeV - 32) + 17, @SetupHeart);
  144.                     3: 
  145.                         mp := SATNewSprite(-2, gSAT.offSizeH - xsize, Rand(gSAT.offSizeV - 32) + 17, @SetupHeart);
  146.                 end;
  147.         end;
  148.  
  149.     begin { SetupLevel }
  150.  
  151. { Clear the sprite list }
  152.         while gSAT.sRoot <> nil do
  153.             SATKillSprite(gSAT.sRoot);
  154.  
  155. { Create all the sprites for the level, depending on the level number. }
  156.         case level of
  157.             1: 
  158.                 begin
  159.                     bonus := 250;
  160.                     MakeHearts(6);
  161.                     mp := SATNewSprite(-3, 10, 10, @SetupFlypaper);
  162.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  163.                 end;
  164.             2: 
  165.                 begin
  166.                     bonus := 300;
  167.                     MakeHearts(10);
  168.                     mp := SATNewSprite(-3, 10, 10, @SetupFlypaper);
  169.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, 20, @SetupFlypaper);
  170.                     mp := SATNewSprite(-3, 20, gSAT.offSizeV - 32, @SetupFlypaper);
  171.                 end;
  172.             3: 
  173.                 begin
  174.                     MakeHearts(12);
  175.                     bonus := 350;
  176.                     mp := SATNewSprite(-3, 5, 5, @SetupFlypaper);
  177.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, 5, @SetupFlypaper);
  178.                     mp := SATNewSprite(-3, 5, gSAT.offSizeV - 32, @SetupFlypaper);
  179.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  180.                 end;
  181.             4: 
  182.                 begin
  183.                     MakeHearts(12);
  184.                     bonus := 350;
  185.                     mp := SATNewSprite(-3, 5, 5, @SetupFlypaper);
  186.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, 5, @SetupFlypaper);
  187.                     mp := SATNewSprite(-3, 5, gSAT.offSizeV - 32, @SetupFlypaper);
  188.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  189.                     mp := SATNewSprite(-3, 5, (gSAT.offSizeV - 32) mod 2, @SetupFlypaper);
  190.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, (gSAT.offSizeV - 32) mod 2, @SetupFlypaper);
  191.                 end;
  192.             5: 
  193.                 begin
  194.                     MakeHearts(10);
  195.                     bonus := 380;
  196.                     mp := SATNewSprite(-3, 5, 5, @SetupFlypaper);
  197.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, 5, @SetupFlypaper);
  198.                     mp := SATNewSprite(-3, 5, gSAT.offSizeV - 32, @SetupFlypaper);
  199.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  200.                 end;
  201.             6: 
  202.                 begin
  203.                     MakeHearts(12);
  204.                     bonus := 420;
  205.                     mp := SATNewSprite(-3, 5, 5, @SetupFlypaper);
  206.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, 5, @SetupFlypaper);
  207.                     mp := SATNewSprite(-3, 5, gSAT.offSizeV - 32, @SetupFlypaper);
  208.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  209.                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, (gSAT.offSizeV - 32) mod 2, @SetupFlypaper);
  210.                 end;
  211.             otherwise
  212.                 begin
  213.                     MakeHearts(level * 2);
  214.                     bonus := 300 + 20 * level;
  215.                     for i := 0 to level - 1 do
  216.                         begin
  217.                             case rand(6) of
  218.                                 0: 
  219.                                     mp := SATNewSprite(-3, 5, 5, @SetupFlypaper);
  220.                                 1: 
  221.                                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, 5, @SetupFlypaper);
  222.                                 2: 
  223.                                     mp := SATNewSprite(-3, 5, 300, @SetupFlypaper);
  224.                                 3: 
  225.                                     mp := SATNewSprite(-3, gSAT.offSizeH - xsize - 32, gSAT.offSizeV - 32, @SetupFlypaper);
  226.                                 4: 
  227.                                     mp := SATNewSprite(-3, (gSAT.offSizeH - xsize - 32) div 2, 5, @SetupFlypaper);
  228.                                 5: 
  229.                                     mp := SATNewSprite(-3, (gSAT.offSizeH - xsize - 32), gSAT.offSizeV - 32, @SetupFlypaper);
  230.                             end; { case }
  231.                         end;
  232.                 end;
  233.         end;
  234.  
  235.         bonusLevelRunning := false;
  236.  
  237. { Reposition mouse to the center of the game area. }
  238.         p.h := 256;
  239.         p.v := 171;
  240.         SetMouse(p);
  241. { Make the player sprite. }
  242.         mp := SATNewSprite(2, (gSAT.offSizeH - xsize) div 2, gSAT.offSizeV div 2, @SetupPlayer);
  243. { Copy gSAT.backScreen to gSAT.offScreen to erase old sprites. }
  244.         CopyBits(gSAT.backScreen^.portBits, gSAT.offScreen^.portBits, gSAT.offScreen^.portRect, gSAT.offScreen^.portRect, srcCopy, nil);
  245.         SATRedraw; {replaces the following out-commented lines:}
  246.  
  247.         AddScore(0);
  248. { Do one frame of animation just to draw all the objects. }
  249.         SATRun(false); {false or features^^.PlotFast; slow is ok - no hurry!}
  250.  
  251.         if level = 1 then
  252.             s := MyGetIndString(startgameStrID)  {str 16: Click the mouse to start the game.}
  253.         else
  254.             s := stringof(MyGetIndString(startlevelStrID), level : 1, '.'); {str 17: Click the mouse to start level }
  255.  
  256.         if level = 1 then
  257.             strwidth := StringWidth(s)
  258.         else
  259.             strwidth := StringWidth(s);
  260.  
  261. { Draw a message and wait for click- this is a bit ugly. Consider other ways. }
  262.         SetPort(gSAT.wind);
  263.         SetRect(r, gSAT.offSizeH div 2 - strwidth div 2 - 5 + 2, gSAT.offSizeV div 2 + 35 + 2, gSAT.offSizeH div 2 + strwidth div 2 + 5 + 2, gSAT.offSizeV div 2 + 60 + 2); {offset by 2 pixels}
  264.         PaintRect(r);
  265.         SetRect(r, gSAT.offSizeH div 2 - strwidth div 2 - 5, gSAT.offSizeV div 2 + 35, gSAT.offSizeH div 2 + strwidth div 2 + 5, gSAT.offSizeV div 2 + 60);
  266.         EraseRect(r);
  267.  
  268.         MoveTo(gSAT.offSizeH div 2 - strwidth div 2, gSAT.offSizeV div 2 + 50);
  269.         DrawString(s);
  270.  
  271. {Wait until something happens}
  272.         FlushEvents(EveryEvent, 0); { To forget events, like mouse clicks etc. }
  273.         repeat
  274.         until EventAvail(mDownMask + keyDownMask, er);
  275.  
  276. { Redraw to get rid of the message we just made. }
  277.         SATRedraw;
  278.     end; { SetupLevel }
  279.  
  280. { Start a new game. Initialize level, score, number of lives, and call setuplevel to make the first level. }
  281.     procedure StartGame;
  282.     begin
  283.         ZeroScore;
  284.         level := 1;
  285.  
  286.         bonusesCollected := 0;
  287.  
  288.         SetupLevel(level);
  289.     end;
  290.  
  291. { Game Over procedure. Draw "Game Over" text, check high scores. }
  292.  
  293.     procedure DoGameOver;
  294.         var
  295. { Variables for the Game Over-box }
  296.             theRect, theRect2: rect;
  297.             thePict: Handle;
  298.             bredd, i: integer;
  299.             dx, dy: integer;
  300.             time: longint;
  301.     begin
  302.         SetItem(GameMenu, Pause, MyGetIndString(pauseStrID)); {str 18: Pause}
  303. { Game Over display! }
  304.         SetPort(gSAT.wind);
  305.         if gSAT.colorFlag and (gSAT.initDepth <> 1) then
  306.             thePICT := GetResource('PICT', 129)
  307.         else
  308.             thePICT := GetResource('PICT', 128);
  309.         theRect := PicHandle(thePICT)^^.picFrame;
  310.         theRect.right := theRect.right - theRect.left;
  311.         theRect.bottom := theRect.bottom - theRect.top;
  312.         theRect.top := 0;
  313.         theRect.left := 0;
  314.  
  315.         dx := (gSAT.offSizeH - (theRect.right - theRect.left)) div 2 - theRect.left;
  316.         dy := (gSAT.offSizeV - (theRect.bottom - theRect.top)) div 2 - theRect.top;
  317.         OffsetRect(theRect, dx, dy);
  318.  
  319.         bredd := theRect.right - theRect.left;
  320.         theRect2 := theRect;
  321.  
  322.         i := 1;
  323.         repeat
  324.             time := TickCount;
  325.             theRect.right := theRect2.right - bredd * (80 - i) div 160;
  326.             theRect.left := theRect2.left + bredd * (80 - i) div 160;
  327.             DrawPicture(PicHandle(thePICT), TheRect);
  328.             i := i + TickCount - time;
  329.         until i >= 80;
  330.  
  331.         SetPort(gSAT.offScreen);
  332.         DrawPicture(PicHandle(thePICT), TheRect);
  333.         SetPort(gSAT.wind);
  334.  
  335.         InvalRect(theRect);
  336.  
  337.         SATSoundShutUp; { Dispose of sound channel }
  338.  
  339.         FlushEvents(everyEvent, 0); { To forget events, like mouse clicks etc. }
  340.         ShowCursor;
  341.  
  342.         UpdateHigh; { Game over, was it high score? }
  343.     end;
  344.  
  345.  
  346. { This routine is the game driver. It calls the "Animator" package until the game ends or is paused. }
  347. { I also read the keyboard here. This could optionally be moved to the "player object" module. }
  348.  
  349.     procedure MoveIt;
  350.         var
  351.             fr, tr, r: Rect;
  352.             pt: Point;
  353.             t, l: longint;
  354.             theEvent: EventRecord; { för att testa musklick }
  355. { To check for key clicks with GetKeys:  - no longer used. km: KeyMap;}
  356.             hasEvent: Boolean;
  357.             ignore: OSerr;
  358.     begin
  359.         stillrunning := true; { A flag that tells whether or not to quit this routine. }
  360.  
  361.         HideCursor; { NOTE: No matter how we leave the MoveIt procedure, we should ShowCursor. }
  362.  
  363.         pt.h := 256;
  364.         pt.v := 171;
  365.         SetMouse(pt);
  366.  
  367. { Main loop! Keep running until the game is paused or ends. }
  368.         while stillrunning = true do
  369.             begin
  370.                 t := TickCount;
  371.                 SetPort(gSAT.wind);
  372.                 SetPort(gSAT.offScreen);
  373.  
  374. {Reset booleans that will be set by the sprites.}
  375.                 bonusObjectRunning := false;
  376.                 levelCompleted := true;
  377.  
  378. { Here is the real heart of the loop: call Animator once per loop. It will call all the objects. }
  379.                 SATRun(features^^.plotFast);
  380. {SATSoundEvents; No longer needed - included in SATRun!}
  381.  
  382. { All the rest of the main loop is game specific, next level, bonus handling, etc. }
  383.  
  384. {Decrease bonus. Out of bonus? Does not apply to bonus levels.}
  385.                 if not bonusLevelRunning then
  386.                     if not bonusObjectRunning or features^^.macho then
  387.                         if bonus > 0 then
  388.                             begin
  389.                                 bonus := bonus - 1;
  390.                                 if bonus mod 10 = 0 then
  391.                                     begin
  392.                                         AddScore(0);
  393.                                         if features^^.macho then
  394.                                             if bonus < 110 then
  395.                                                 SATSoundPlay(TickSndH, 0, false);
  396.                                     end
  397.                                 else if features^^.macho then
  398.                                     if bonus < 26 then
  399.                                         if bonus mod 5 = 0 then
  400.                                             SATSoundPlay(TickSndH, 0, false);
  401.                             end
  402.                         else if features^^.macho then
  403.                             stillrunning := false;
  404.  
  405.                 if levelCompleted then{(batchcount < 1)}
  406.         {All hearts collected?}
  407.                     begin
  408.                         SATSoundShutUp;
  409.  
  410.                         SATSoundPlay(sadarSndH, 0, true);
  411.                         repeat
  412.                             SATSoundEvents
  413.                         until SATSoundDone;
  414.  
  415. {If it isn't a bonus level, we should give the player the bonus remaining}
  416.                         if not bonusLevelRunning then
  417.                             if bonus > 0 then
  418.                                 while bonus > 0 do
  419.                                     begin
  420.                                         bonus := bonus - 10;
  421.  
  422.                                         SATSoundPlay(KlounkSndH, 0, true);
  423.                                         repeat
  424.                                             SATSoundEvents
  425.                                         until SATSoundDone;
  426.  
  427.                                         if bonus < 0 then
  428.                                             begin
  429.                                                 l := bonus;
  430.                                                 bonus := 0;
  431.                                                 AddScoreS(10 + l); {A special synchronous version of AddScore}
  432.                                             end
  433.                                         else
  434.                                             AddScoreS(10); { Bonus! }
  435.                                     end { if bonus > 0 }
  436.                             else if features^^.macho then
  437.                                 stillrunning := false; { If no bonus, game over }
  438.  
  439. {Level finished? Do we want a new level?}
  440.                         if (stillrunning and features^^.macho) or (level < 3) then
  441.                             if bonusesCollected >= kBonusLevelTresh then
  442.                                 begin
  443.                                     SetupBonusLevel(level);
  444.                                     AddScoreS(0); {To update the level number}
  445.                                     bonusesCollected := bonusesCollected - kBonusLevelTresh;
  446.                                 end
  447.                             else
  448.                                 begin
  449.                                     level := level + 1;
  450.                                     SetupLevel(level);
  451.                                     AddScoreS(0); {To update the level number}
  452.                                 end
  453.                         else
  454.                             stillrunning := false;
  455.                     end; {if (batchcount < 1)}
  456.  
  457. { Check for keys being pressed }
  458.                 if features^^.allowBG then { if we are allowed to use the normal method }
  459.                     begin
  460.                         SystemTask;
  461. { Replaced the following call by WaitNextEvent if you want to be modern (but less backwards compatible). :-) }
  462.                         hasEvent := GetNextEvent(keyDownMask, theEvent)
  463.                     end
  464.                 else {Otherwise, use the faster GetOSEvent}
  465.                     begin
  466.                         hasEvent := GetOSEvent(keyDownMask, theEvent)
  467.                     end;
  468.  
  469. {If there was a keydown, see if it was one of the menu options that we support when running.}
  470.                 if hasEvent then { there was a keydown }
  471.                     if BitAnd(theEvent.modifiers, cmdKey) <> 0 then
  472.                         begin
  473.                             case char(BitAnd(theEvent.message, charCodeMask)) of
  474.                                 'p': 
  475.                                     begin
  476.                                         PauseFlag := true;
  477.                                         SATSoundShutUp; { Dispose of sound channel }
  478.                                         ShowCursor;
  479.                                         flushevents(6 + 8, 0); { In order to forget the cmd-p }
  480.                                         SetItem(GameMenu, Pause, MyGetIndString(resumeStrID)); {str 19: Resume}
  481.                                         exit(MoveIt);
  482.                                     end;
  483.                                 '.': 
  484.                                     StillRunning := false;
  485.                                 'q': 
  486.                                     begin
  487.                                         StillRunning := false;
  488.                                         SkelWhoa;
  489.                                     end;
  490.                                 's': 
  491.                                     begin
  492.                                         DoGameMenu(sound);
  493.                                     end;
  494.                                 otherwise
  495.                                     ;
  496.                             end; {case}
  497.                         end
  498.                     else if BitAnd(theEvent.message, charCodeMask) = 27 then {ESC}
  499.                         StillRunning := false;
  500.  
  501. { Delay, using TickCount so it doesn't matter how fast our Mac is. }
  502.                 while ((TickCount - t) < 3) do
  503.                     ;
  504.  
  505.             end; { while stillrunning (main loop) }
  506.  
  507.         DoGameOver;
  508.  
  509.         FlushEvents(mouseDown + keyDown, 0); { In order to forget the cmd-p }
  510.     end;
  511.  
  512.  
  513. {We used to draw the background ourselves rather than using a simple backdrop PICT, to save space and to get}
  514. {the dithered background. However, using the shades in the object drawing part of ClarisWorks, I can make PICT}
  515. {resources that are fairly small, so I use that instead now.}
  516. {Thus, DrawBackground ONLY draws the trees!}
  517.     procedure DrawBackground;
  518.         var
  519.             ph: PicHandle;
  520.             ignore: OSErr;
  521.             col: RGBColor;
  522.             thinr, r: Rect;
  523.             i, j: integer;
  524.  
  525.             posH, posV, scale, height, width: longint; {For scaling the trees}
  526.     begin
  527.         SATSetPortBackScreen;
  528.         SetRect(r, 0, 0, gSAT.offSizeH, gSAT.offSizeV);
  529.  
  530. {Draw trees using PICTs!}
  531.  
  532. {First get the right PICT}
  533.         if gSAT.initDepth = 1 then
  534.             begin
  535.                 ph := GetPicture(135); {bw tree PICT}
  536.             end
  537.         else
  538.             begin
  539.                 ph := GetPicture(134); {color tree PICT}
  540.             end;
  541.         if ph = nil then
  542.             exit(DrawBackground);
  543.  
  544. {Scale by ph^^.picframe}
  545.         for i := 0 to 10 do
  546. {For more trees: for j := i to 4 do}
  547.             begin
  548.                 posH := Rand(gSAT.offSizeH);
  549.                 posV := gSAT.offSizeV div 2 + longint(i) * i * gSAT.offSizeV div 300;
  550.  
  551.                 scale := (posV - gSAT.offSizeV div 4) div 17;
  552.                 height := scale * (ph^^.picframe.bottom - ph^^.picframe.top) div 40;
  553.                 width := scale * (ph^^.picframe.right - ph^^.picframe.left) div 40;
  554.  
  555.                 r.top := posV - height;
  556.                 r.bottom := posV;
  557.                 r.right := posH + width;
  558.                 r.left := posH;
  559.  
  560.                 DrawPicture(ph, r);
  561.             end;
  562.  
  563.         ReleaseResource(handle(ph));
  564.  
  565.         CopyBits(gSAT.backScreen^.portBits, gSAT.offScreen^.portBits, gSAT.backScreen^.portRect, gSAT.backScreen^.PortRect, srcCopy + ditherCopy, nil);
  566.         SATSetPortScreen;
  567.         SATRedraw;
  568. {CopyBits(gSAT.backScreen^.portBits, gSAT.wind^.portBits, gSAT.backScreen^.portRect, gSAT.backScreen^.PortRect, srcCopy + ditherCopy, nil);}
  569.     end;
  570.  
  571.  
  572.     procedure GameWindUpdate;
  573.         var
  574.             s: str255;
  575.             r: Rect;
  576.             crsr: CursHandle;
  577.     begin
  578. {When the depth has changed, the game wind will get an update event,}
  579. {so let's give SAT a chance to update itself before updating!}
  580.  
  581.         crsr := GetCursor(WatchCursor);
  582.         SetCursor(crsr^^);
  583.         if SATDepthChangeTest then
  584.             begin
  585.                 DrawBackground;    {Redraw trees}
  586.             end;
  587.         ReleaseResource(handle(crsr));
  588.         InitCursor;
  589.  
  590.         SATRedraw;
  591.         AddScore(0);
  592.     end;
  593.  
  594.     procedure DoGameMenu (item: integer);
  595.     begin
  596.         case (item) of
  597.             run: 
  598.                 begin
  599. { Test if we have Color QD, and if so, test bit depth! Alert if features^^.PlotFast.}
  600.                     if SATDepthChangeTest then {Update if necessary}
  601.                         DrawBackground;
  602.                     if not ((gSAT.initDepth = 1) or (gSAT.initDepth = 4) or (gSAT.initDepth = 8)) and features^^.PlotFast then
  603.                         begin
  604.                             reportstr(MyGetIndString(pleaseuncheckStrID));
  605. {str 23: Please uncheck ''Fast animation'' or set the monitor to 1-, 4- or 8-bit mode in the Control Panel.}
  606.                             exit(DoGameMenu);
  607.                         end;
  608.                     if pauseFlag then
  609.                         if QuestionStr(MyGetIndString(endStrID)) then {str 24: End the Current game?}
  610.                             DoGameMenu(abort)
  611.                         else
  612.                             exit(DoGameMenu);
  613.                     DisableItem(gameMenu, macho);
  614.                     ShowWindow(gSAT.wind);
  615.                     SelectWindow(gSAT.wind);
  616.                     StartGame;
  617.                     GameWindUpdate;
  618.                     MoveIt;
  619.                     if not pauseFlag then
  620.                         EnableItem(GameMenu, macho);
  621.                 end;
  622.             sound: 
  623.                 begin
  624.                     features^^.sound := not features^^.sound;
  625.                     CheckItem(GameMenu, sound, features^^.sound);
  626.                     if features^^.sound then { Tell the sound package our settings, so we don't have to bother. }
  627.                         SATSoundOn
  628.                     else
  629.                         SATSoundOff;
  630.                     ChangedResource(handle(features));
  631.                 end;
  632.             macho: 
  633.                 begin
  634.                     features^^.macho := not features^^.macho;
  635.                     CheckItem(GameMenu, macho, features^^.macho);
  636.                     ChangedResource(handle(features));
  637.                 end;
  638.             AllowBG: 
  639.                 begin
  640.                     features^^.AllowBG := not features^^.AllowBG;
  641.                     CheckItem(GameMenu, AllowBG, features^^.AllowBG);
  642.                     ChangedResource(handle(features));
  643.                 end;
  644.             FastAnimation: 
  645.                 begin
  646.                     features^^.PlotFast := not features^^.PlotFast;
  647.                     CheckItem(GameMenu, FastAnimation, features^^.PlotFast);
  648.                     ChangedResource(handle(features));
  649.                 end;
  650.             pause: 
  651.                 begin
  652. { Pause is only interesting here as "resume". }
  653.                     if pauseFlag then
  654.                         begin
  655. { Test if we have Color QD, and if so, test bit depth! Alert if features^^.PlotFast.}
  656.                             if SATDepthChangeTest then {Update if necessary}
  657.                                 DrawBackground;
  658.                             if not ((gSAT.initDepth = 1) or (gSAT.initDepth = 4) or (gSAT.initDepth = 8)) and features^^.PlotFast then
  659.                                 begin
  660.                                     ReportStr(MyGetIndString(pleaseuncheckStrID)); {str 23}
  661.                                     exit(DoGameMenu);
  662.                                 end;
  663.                             SetItem(GameMenu, pause, MyGetIndString(pauseStrID)); {str 18}
  664.                             pauseFlag := false;
  665.                             ShowWindow(gSAT.wind);
  666.                             SelectWindow(gSAT.wind);
  667.                             GameWindUpdate;
  668.                             MoveIt;
  669.                             if not pauseFlag then
  670.                                 EnableItem(GameMenu, macho);
  671.                         end;
  672.                 end;
  673.             abort: 
  674.                 begin
  675.                     if pauseFlag then
  676.                         begin
  677.                             SetItem(GameMenu, Pause, MyGetIndString(pauseStrID)); {str 18}
  678.                             DoGameOver;
  679.                             pauseFlag := false;
  680.                             EnableItem(GameMenu, macho);
  681.                         end
  682.                 end;
  683.         end;
  684.     end;
  685.  
  686.     procedure GameWindMouse (thePoint: Point; theTime: longint; theMods: integer; myProc: ProcPtr);
  687.     begin
  688.         if pauseFlag then
  689.             DoGameMenu(pause)
  690.         else
  691.             DoGameMenu(run);
  692.     end;
  693.  
  694.     procedure GameWindIdle;
  695.     begin
  696.     end;
  697.  
  698.     procedure GameWindClose;
  699.     begin
  700.     end;
  701.  
  702.     procedure GameWindInit;
  703.     begin
  704. { Tell TransSkel to handle all the tedious things with gSAT.wind. }
  705.         dummy := SkelWindow(gSAT.wind, @GameWindMouse, nil, @GameWindUpdate, nil, @GameWindClose, nil, @GameWindIdle, false);
  706.  
  707. { Initialize the sprites }
  708.         InitSprites;
  709.  
  710. {We draw some of the background -the trees - ourselves in this game.}
  711.         DrawBackground;
  712.  
  713. { Draw the contents of the window (to give the user something to look at during the rest of startup). }
  714.         ShowWindow(gSAT.wind);
  715.         SelectWindow(gSAT.wind);
  716.         SATRedraw;
  717.     end;
  718.  
  719. end.